/**********************************************************************
 *<
	FILE: IDX8VertexShader.h

	DESCRIPTION: DirectX 8 Vertex Shader Interface Definition

	CREATED BY: Nikolai Snader and Norbert Jeske

	HISTORY: Created 9/22/00

 *>	Copyright (c) 2000, All Rights Reserved.
 **********************************************************************/
#pragma once

#include "maxheap.h"
#include <d3dx8.h>
#include "IHardwareShader.h"

#define DX8_VERTEX_SHADER_INTERFACE_ID Interface_ID(0x476a10d9, 0x7f531d40)

struct DX8VSConstant: public MaxHeapOperators
{
	float a,b,c,d;
	
	// Access operators
	float& operator[](int i) { return (&a)[i]; }     
	const float& operator[](int i) const { return (&a)[i]; }  
};

class ID3DGraphicsWindow;
class IDX8PixelShader;

/*! \sa  Class IVertexShader, Class IDX8PixelShader\n\n
\par Description:
This class is available in release 4.0 and later only.\n\n
The abstract interface to the Direct-3D Vertex Shader architecture.\n\n
The drawing functions are necessary as something other than a simple default
body if: <ul> <li>The VertexShader needs to add additional per vertex data
unknown to the Mesh to the VertexBuffer. </li> <li>The VertexShader needs to
have per vertex data ordered differently than the standard position, normal,
{color, tex coords ordering}. </li> <li>The VertexShader is being used to
create cached VertexBuffers or using higher order surfaces. </li> </ul> \n In the
cases of <b>DrawMeshStrips()</b> and <b>DrawWireMesh()</b>, the VertexShader
has the option of not only locking and filling the VertexBuffer with data, but
also of making the actual DrawPrimitive call. In the case of
<b>StartLines()</b>, the VertexShader must make the DrawPrimitive call. The
VertexShader indicates that it has done the drawing by returning 'true' in the
Draw functions provided.\n\n
In the case where the VertexShader does not want to do the drawing but does
want to fill in a VertexBuffer with data, the VertexShader can request the GFX
to create a VertexBuffer (and possibly an IndexBuffer) of appropriate size. The
GetVertexBuffer and GetIndexBuffer calls on the ID3DGraphicsWindow object will
do this and return the allocated buffers in subsequent calls or reallocate them
if necessary.\n\n
Please note that if a PixelShader or PixelShaders are in use, these Draw
functions may need to set them for the appropriate passes of a multipass
rendering if the drawing is done in these Draw() functions. If the GFX is doing
the drawing, then these Draw() functions are only being used to fill in the
VertexBuffer with data; the GFX will be doing the drawing and will be setting
the PixelShaders as appropriate.  */
class IDX8VertexShader : virtual public IVertexShader, public BaseInterface
{
public:
	/*! \remarks This method returns the interface ID of the class.
	\par Default Implementation:
	<b>{ return DX8_VERTEX_SHADER_INTERFACE_ID; }</b> */
	virtual Interface_ID GetID() { return DX8_VERTEX_SHADER_INTERFACE_ID; }

	// Confirm that the Direct3D Device can handle this VertexShader
	/*! \remarks This method will confirm that the Direct3D Device can handle
	this VertexShader.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window. */
	virtual HRESULT ConfirmDevice(ID3DGraphicsWindow *gw) = 0;

	// Confirm that an associated PixelShader will work with this VertexShader
	/*! \remarks This method will confirm that an associated PixelShader will
	work with this VertexShader.
	\par Parameters:
	<b>IDX8PixelShader *pps</b>\n\n
	A pointer to the pixel shader to confirm for. */
	virtual HRESULT ConfirmPixelShader(IDX8PixelShader *pps) = 0;

	// Can try tristrips for drawing or must geometry using this VertexShader
	// be drawn as triangles?  This should return 'true' unless additional per
	// vertex data is generated by this VertexShader and this data does not map
	// to the Mesh vertices in the same way as existing data the Mesh knows
	// about such as texture coordinates.
	/*! \remarks This method will indicate if it can try tristrips for drawing
	or must geometry using this VertexShader be drawn as triangles? This should
	return TRUE unless additional per vertex data is generated by this
	VertexShader and this data does not map to the Mesh vertices in the same
	way as existing data the Mesh knows about such as texture coordinates. */
	virtual bool CanTryStrips() = 0;

	// Number of passes for the effect this VertexShader creates.  Note that
	// this value will depend on the hardware currently in use.
	/*! \remarks This method returns the number of passes for the effect this
	VertexShader creates. Note that this value will depend on the hardware
	currently in use. */
	virtual int GetNumMultiPass() = 0;

	// Retrieve the VertexShader handle for the specified pass for use in GFX
	/*! \remarks This method returns the VertexShader handle for the specified
	pass for use in GFX. */
	virtual DWORD GetVertexShaderHandle(int numPass) = 0;

	// Set the VertexShader for the specified pass.  This call will be made at
	// least once per object to set the per object data for the VertexShader
	// such as the VertexShader constants.
	/*! \remarks This method allows you to set the VertexShader for the
	specified pass. This call will be made at least once per object to set the
	per object data for the VertexShader such as the VertexShader constants.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window.\n\n
	<b>int numPass</b>\n\n
	The pass for which to set the vertex shader. */
	virtual HRESULT SetVertexShader(ID3DGraphicsWindow *gw, int numPass) = 0;


	// Drawing functions.  These functions are necessary as something other
	// than a simple default body if:
	//
	// 1. The VertexShader needs to add additional per vertex data unknown to
	//    the Mesh to the VertexBuffer.
	//
	// 2. The VertexShader needs to have per vertex data ordered differently
	//    than the standard position, normal, {color, tex coords ordering}.
	//
	// 3. The VertexShader is being used to create cached VertexBuffers or
	//    using higher order surfaces.
	//
	// In the first two cases, the VertexShader has the option of not only
	// locking and filling the VertexBuffer with data, but also of making the
	// actual DrawPrimitive call.  In the third case, the VertexShader must
	// make the DrawPrimitive call.  The VertexShader indicates that it has
	// done the drawing by returning 'true' in the Draw() functions below.
	//
	// In the case where the VertexShader does not want to do the drawing but
	// does want to fill in a VertexBuffer with data, the VertexShader can
	// request the GFX to create a VertexBuffer (and possibly an IndexBuffer)
	// of appropriate size.  The GetVertexBuffer and GetIndexBuffer calls on
	// the ID3DGraphicsWindow object will do this and return the allocated
	// buffers in subsequent calls or reallocate them if necessary.
	//
	// Please note that if a PixelShader or PixelShaders are in use, these
	// Draw() functions may need to set them for the appropriate passes of a
	// multipass rendering if the drawing is done in these Draw() functions.
	// If the GFX is doing the drawing, then these Draw() functions are only
	// being used to fill in the VertexBuffer with data; the GFX will be doing
	// the drawing and will be setting the PixelShaders as appropriate.


	// Draw 3D Mesh as TriStrips.  Fill in the VertexBuffer with data in the
	// order desired by the VertexShader.  Return 'true' if the Mesh has
	// actually been drawn in this call, 'false' if the GFX is required to make
	// the DrawPrimitive call.
	/*! \remarks This method will draw the 3D Mesh as TriStrips. Fill in the
	VertexBuffer with data in the order desired by the VertexShader.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window.\n\n
	<b>MeshData *data</b>\n\n
	A pointer to the mesh data.
	\return  TRUE if the Mesh has actually been drawn in this call, FALSE if
	the GFX is required to make the DrawPrimitive call. */
	virtual bool	DrawMeshStrips(ID3DGraphicsWindow *gw, MeshData *data) = 0;

	// Draw 3D Mesh as wireframe.  Fill in the VertexBuffer with data in the
	// order desired by the VertexShader.  Return 'true' if the Mesh has
	// actually been drawn in this call, 'false' if the GFX is required to make
	// the DrawPrimitive call.
	/*! \remarks This method will draw the 3D Mesh as wireframe. Fill in the
	VertexBuffer with data in the order desired by the VertexShader.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window.\n\n
	<b>WireMeshData *data</b>\n\n
	A pointer to the wire mesh data.
	\return  TRUE if the Mesh has actually been drawn in this call, FALSE if
	the GFX is required to make the DrawPrimitive call. */
	virtual bool	DrawWireMesh(ID3DGraphicsWindow *gw, WireMeshData *data) = 0;


	// Draw 3D lines.  A Mesh is being drawn by having line segments handed
	// down one at a time.

	// Pass in the Mesh data in preparation for drawing 3D lines.
	/*! \remarks This method will draw 3D lines. A Mesh is being drawn by
	having line segments handed\n\n
	down one at a time. Pass in the Mesh data in preparation for drawing 3D
	lines.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window.\n\n
	<b>WireMeshData *data</b>\n\n
	A pointer to the wire mesh data. */
	virtual void	StartLines(ID3DGraphicsWindow *gw, WireMeshData *data) = 0;

	// Add the connectivity information for one two point line segment.
	/*! \remarks This method will draw 3D lines. A Mesh is being drawn by
	having line segments handed\n\n
	down one at a time. Add the connectivity information for one two point line
	segment.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window.\n\n
	<b>DWORD *vert</b>\n\n
	The array of vertices.\n\n
	<b>int vis</b>\n\n
	The visibility flag. */
	virtual void	AddLine(ID3DGraphicsWindow *gw, DWORD *vert, int vis) = 0;

	// Draw the line segments accumulated.  This should restart the filling of
	// a VertexBuffer with the next AddLine call if additional data needs to
	// be drawn before EndLines is called.  Return 'true' if the Mesh line
	// segments have actually been drawn in this call, 'false' if the GFX is
	// required to make the DrawPrimitive call.
	/*! \remarks This method will draw the line segments accumulated. This
	should restart the filling of a VertexBuffer with the next AddLine call if
	additional data needs to be drawn before EndLines is called.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window.
	\return  TRUE if the Mesh line segments have actually been drawn in this
	call, FALSE if the GFX is required to make the DrawPrimitive call. */
	virtual bool	DrawLines(ID3DGraphicsWindow *gw) = 0;

	// Let the Mesh know that all drawing and data access is finished.
	/*! \remarks This method will let the Mesh know that all drawing and data
	access is finished.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window.\n\n
	<b>GFX_ESCAPE_FN fn</b>\n\n
	The graphics escape function. */
	virtual void	EndLines(ID3DGraphicsWindow *gw, GFX_ESCAPE_FN fn) = 0;


	// Draw 3D triangles.  A Mesh is being drawn by having triangles handed
	// down one at a time.

	// Pass in the Mesh data in preparation for drawing 3D triangles.
	/*! \remarks This method will Draw 3D triangles. A Mesh is being drawn by
	having triangles handed down one at a time. Pass in the Mesh data in
	preparation for drawing 3D triangles.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window.\n\n
	<b>MeshFaceData *data</b>\n\n
	A pointer to the mesh face data. */
	virtual void	StartTriangles(ID3DGraphicsWindow *gw, MeshFaceData *data) = 0;

	// Add the connectivity information for one triangle.
	/*! \remarks This method will Draw 3D triangles. A Mesh is being drawn by
	having triangles handed down one at a time. Add the connectivity
	information for one triangle.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window.\n\n
	<b>DWORD index</b>\n\n
	The triangle index.\n\n
	<b>int *edgeVis</b>\n\n
	The array of edge visibility information/ */
	virtual void	AddTriangle(ID3DGraphicsWindow *gw, DWORD index, int *edgeVis) = 0;

	// Draw the triangles accumulated.  This should restart the filling of a
	// VertexBuffer with the next AddTriangle call if additional data needs to
	// be drawn before EndTriangles is called.  Return 'true' if the Mesh
	// triangles have actually been drawn in this call, 'false' if the GFX is
	// required to make the DrawPrimitive call.
	/*! \remarks This method will draw the triangles accumulated. This should
	restart the filling of a VertexBuffer with the next AddTriangle call if
	additional data needs to be drawn before EndTriangles is called. Return
	'true' if the Mesh triangles have actually been drawn in this call, 'false'
	if the GFX is required to make the DrawPrimitive call.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window. */
	virtual bool	DrawTriangles(ID3DGraphicsWindow *gw) = 0;

	// Let the Mesh know that all drawing and data access is finished.
	/*! \remarks This method will let the Mesh know that all drawing and data
	access is finished.
	\par Parameters:
	<b>ID3DGraphicsWindow *gw</b>\n\n
	A pointer to the Direct-3D Graphics Window.\n\n
	<b>GFX_ESCAPE_FN fn</b>\n\n
	The graphics escape function. */
	virtual void	EndTriangles(ID3DGraphicsWindow *gw, GFX_ESCAPE_FN fn) = 0;
};
